import React from 'react';
import styles from './index.module.scss';
import {NumberSize} from "re-resizable";
import ResizeBox from "./ResizeBox";
import ChartRender from "./ChartRender";
import {DraggableCore} from 'react-draggable';
import {DeleteOutlined, CopyOutlined} from '@ant-design/icons';

import {throttle, round} from 'lodash'

import * as classnames from "classnames";
import {EE, prompt} from "@/utils";
import EnumOnFire from "@/pages/dv/constants/EnumOnFire";
import dvTool from "@/pages/dv/dvTool";
import drawTool from "@/pages/dv/drawTool";
import {Tooltip} from "@/components/wocloud-antd";

interface IProps {
  chartOption: DV.IChart,
}

interface IState {
  scale: number;
  left: number;
  top?: number,
  width?: number,
  height?: number,
}

/**
 * chart容器
 * 1、尺寸调整
 * 2、位置调整
 * 3、组件状态调整
 * 4、组件挂载
 * @constructor
 */
export default class EditChartContainer extends React.PureComponent<IProps, IState> {
  public boxRef: any;
  public maskRef: any;
  public chartContainerRef: any;
  public chartContentRef: any;
  public position: { left: number; top: number; };
  public chartOption: IBaseConfig;
  public uid: string;
  public ex: number;
  public ey: number;
  public isHover: boolean;
  public selected: boolean;
  public active: boolean;

  constructor(props: IProps) {
    super(props);
    this.uid = props.chartOption.uid || '';
    this.state = {
      scale: dvTool.scale,
      // // 自有的状态，内部更新，不影响其他
      top: props.chartOption.top,
      left: props.chartOption.left || 0,
      width: props.chartOption.width,
      height: props.chartOption.height,
    }
    // 公共状态，持续更新数据，但不会主动触发更新行为
    this.position = {
      left: this.state.left,
      top: this.state.top || 0,
    };
    this.boxRef = null;
    this.chartContainerRef = null;
    this.ex = 0;
    this.ey = 0;
    this.isHover = false;
    this.selected = (this.uid === dvTool.selectedChartKey);
    this.throttleUpdateChartPosition = throttle(this.throttleUpdateChartPosition, 50)
  }

  componentDidMount(): void {
    if (this.selected) {
      this.initFireAction();
      this.initMouseAction();
    }
    // 初始化编辑状态
    this.updateEditStatus({selected: dvTool.selectedChartKey === this.uid});
    // 监听组件变化
    EE.on(EnumOnFire.selectedChartKey, (selectedChartKey: string, chartOption: DV.IChart) => {
      if (selectedChartKey === this.uid) {
        this.updateEditStatus({selected: true});
        this.initFireAction();
        this.initMouseAction();

      } else {
        this.updateEditStatus({selected: false});
        // 取消
        this.initMouseAction(false)
      }
    });
  }

  /**
   * 在选中时初始化订阅事件-----性能优化
   */
  initFireAction() {
    EE.on(EnumOnFire.changeScale, (scale: number) => {
      this.setState({scale})
    });
    EE.on(EnumOnFire.update_size, (chart: DV.IChartRoute) => {
      if (chart[this.uid]) {
        this.updateChartSize(chart[this.uid]);
      }
    });
    EE.on(EnumOnFire.update_position, (chart: DV.IChartRoute) => {
      if (chart[this.uid]) {
        this.updateChartPosition(chart[this.uid]);
      }
    })

    EE.on(EnumOnFire.update_baseConfig, (baseConfig: DV.IChartRoute,) => {
      //  {zIndex, rotate, overflowHidden, opacity, mask}
      if (baseConfig[this.uid]) {
        const config = baseConfig[this.uid];
        if (config.hasOwnProperty('zIndex')) {
          this.boxRef.style.zIndex = config.zIndex;
          this.maskRef.style.zIndex = config.zIndex + 1;
        }
        if (config.hasOwnProperty('rotate')) {
          this.chartContentRef.style.transform = `rotate(${config.rotate}deg)`
        }
        if (config.hasOwnProperty('overflowHidden')) {
          this.chartContainerRef.style.overflow = config.overflowHidden ? 'hidden' : 'unset';
        }
        if (config.hasOwnProperty('opacity')) {
          this.chartContainerRef.style.opacity = config.opacity;
        }
        if (config.hasOwnProperty('mask')) {
          this.maskRef.style.display = config.mask ? 'block' : 'none';
        }
        if (config.hasOwnProperty('className')) {
          try {
            // chart-item
            const box = dvTool.getChartInstance(this.uid).box;
            let oldToken = box.classList.item(1);
            if (oldToken) {
              if (config.className) box.classList.replace(oldToken, config.className)
              else box.classList.remove(oldToken)
            } else {
              box.classList.add(config.className)
            }
          } catch (e) {
          }
        }
      }
    })
  }

  /**
   * 创建捕鼠器
   * @param isInit
   */
  initMouseAction(isInit: boolean = true) {
    if (isInit) {
      // dvTool.MouseAction.reset();
      // dvTool.MouseAction.bind('s', (e, combo) => {
      //   console.log('s1');
      //   if(this.isHover){
      //     console.log(combo);
      //   }
      // });
    } else {
      // dvTool.MouseAction.unbind('s');
    }
  }

  /**
   * 更新组件数据
   * @param size
   */
  updateChartSize(size: NumberSize) {
    // 只更新 尺寸
    this.boxRef.style.width = size.width + 'px';
    this.boxRef.style.height = size.height + 'px';
    this.setState({
      width: size.width,
      height: size.height,
    }, () => {
      try {
        dvTool.getChartInstance(this.uid).chart.resizeChart();
      } catch (e) {
      }
    });
  }

  /**
   * 更新组件的编辑状态
   **/
  updateEditStatus({selected = false}) {
    if (selected) {
      this.selected = true;
      this.boxRef && this.boxRef.classList.add(styles.selected);
      this.boxRef && this.boxRef.classList.remove(styles.isHover, styles.active);
    } else {
      this.selected = false;
      this.boxRef && this.boxRef.classList.remove(styles.selected)
    }
  }

  // 调整大小
  resizeChartSize = ({width, height}: NumberSize) => {
    try {
      const newSize: NumberSize = {
        width,
        height,
      }
      dvTool.updateBaseConfig(this.uid, newSize, true);
    } catch (e) {

    }
  }

  // 延迟更新,限流更新
  throttleUpdateChartPosition(position: IPosition) {
    dvTool.updateBaseConfig(this.uid, position, true);
  }

  // 更新位置
  updateChartPosition(position: IPosition) {
    this.boxRef.style.left = position.left + 'px';
    this.boxRef.style.top = position.top + 'px';
  }

  // 正在拖拽
  onDrag = (e: MouseEvent, {x = 0, y = 0}: IPosition) => {
    // 为增强性能和流畅性，先自我更新，后更新缓存主数据
    this.position.left = round(this.position.left + x - this.ex);
    this.position.top = round(this.position.top + y - this.ey);
    this.updateChartPosition(this.position);
    this.throttleUpdateChartPosition(this.position);

    drawTool.drawDragLines(this.position, dvTool.scale);

  }

  onDragStart = (e: MouseEvent, {x, y}: IPosition) => {
    this.ex = x || 0;
    this.ey = y || 0;
    this.boxRef.classList.add(styles.onDrag)
  }

  onDragStop = (e: MouseEvent, {x, y}: IPosition) => {
    this.ex = 0;
    this.ey = 0;

    this.boxRef.classList.remove(styles.onDrag)
  }

  onMouseEnter = () => {
    this.isHover = true;
    if (this.boxRef) {
      if (!this.boxRef.classList.contains(styles.selected)) {
        this.boxRef.classList.add(styles.isHover);
      }
    }
  }

  onMouseLeave = () => {
    this.isHover = false;
    this.boxRef && this.boxRef.classList.remove(styles.isHover)
  }

  /**
   * 选中组件
   */
  onSelectChart = () => {
    if (dvTool.selectedChartKey !== this.uid) {
      dvTool.selectedChart(this.uid);
    }
  }

  /**
   * 复制组件
   */
  onCopyChart = () => {
    drawTool.drawNewChart(this.props.chartOption?.type || '', this.uid)
  }

  /**
   * 删除组件
   */
  onDeleteChart = () => {
    prompt.confirm(() => {
      dvTool.removeChart(this.uid);
    }, {
      title: '删除组件',
      content: '确定要删除该组件吗？'
    })
  }


  render(): React.ReactNode {
    const {width, height, left, top, scale} = this.state;
    const {zIndex, rotate, overflowHidden, opacity, mask, className} = this.props.chartOption;
    return <div
      className={classnames('dv_chart_item', styles.editorChartBox)}
      id={`chart_${this.uid}`}
      style={{width, height, left, top, zIndex}}
      onMouseEnter={this.onMouseEnter}
      onMouseLeave={this.onMouseLeave}
      onDoubleClick={this.onSelectChart}
      ref={e => this.boxRef = e}
    >
      <div
        className={styles.resize_wrapper}
      >
        {/*----辅助底层图层-------*/}
        <div className={styles.resize_cover}>
          {/*----图表操作工具-------*/}
          <div className={styles.tool}>
            <ul className={styles.actions}>
              <li>
                <Tooltip title={'复制组件'}>
                  <CopyOutlined onClick={this.onCopyChart}/>
                </Tooltip>
              </li>
              <li>
                <Tooltip title={'删除组件'}>
                  <DeleteOutlined onClick={this.onDeleteChart}/>
                </Tooltip>
              </li>
            </ul>
          </div>
          <ResizeBox
            scale={scale}
            width={width}
            height={height}
            resizeChartSize={this.resizeChartSize}
          />
        </div>
        <div
          className={styles.resize_chart_container}
          style={{
            opacity,
            overflow: overflowHidden ? 'hidden' : 'unset',
          }}
          ref={e => this.chartContainerRef = e}
        >
          <DraggableCore
            onStop={this.onDragStop}
            onDrag={this.onDrag}
            onStart={this.onDragStart}
            scale={scale}
          >
            <div
              className={'chart_item__content'}
              style={{
                transform: `rotate(${rotate}deg)`
              }}
              ref={e => this.chartContentRef = e}
            >
              <div
                className={styles.mask}
                style={{zIndex: Number(zIndex) + 1, display: mask ? 'block' : 'none'}}
                ref={e => this.maskRef = e}
              />
              {/*----图表实例渲染位置-------*/}
              <ChartRender
                chartOption={this.props.chartOption}
              />
            </div>
          </DraggableCore>
        </div>
      </div>
    </div>
  }
}
